﻿// Autore: Alessio Parma

using System;
using System.Data.Objects.DataClasses;

namespace RecipesManager.Data.Implementation
{
    sealed partial class Shop : IShop
    {
        readonly IRatings<IIngredient, ShopRating> _ingredientRatings;

        public Shop()
        {
            _ingredientRatings = new ShopRatings(() => IngredientRatings, () => Id);
        }

        #region IShop Members

        string IShop.Address
        {
            get { return Address; }
        }

        string IShop.City
        {
            get { return City; }
        }

        string INamedEntity.Name
        {
            get { return Name; }
        }

        string IShop.PhoneNumber
        {
            get { return PhoneNumber; }
        }

        string IShop.Timetable
        {
            get { return Timetable; }
        }

        IRatings<IIngredient, ShopRating> IShop.IngredientRatings
        {
            get { return _ingredientRatings; }
        }

        public bool Equals(IShop other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Id == other.Id;
        }

        public void Update(string name, string address, string city, string phoneNumber, string timetable)
        {
            Name = name.ToKey();
            Address = address;
            City = city;
            PhoneNumber = phoneNumber;
            Timetable = timetable;
            Manager.SaveChanges();
        }

        #endregion

        public static Shop New(string name, string address, string city, string timetable, string phoneNumber)
        {
            name = name.ToKey();
            return CreateShop(0, name, address, city, timetable, phoneNumber);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            return ReferenceEquals(this, obj) || Equals(obj as IShop);
        }

        public override int GetHashCode()
        {
            return Id;
        }

        public override string ToString()
        {
            return string.Format("Shop(Name: {0})", Name);
        }
    }

    sealed class ShopObjects : NamedObjects<Shop, IShop>, IShops
    {
        public ShopObjects() : base(Manager.ShopSet)
        {
        }

        #region IShops Members

        public IShop Add(string name, string address = "", string city = "", string timetable = "",
                         string phoneNumber = "")
        {
            return Add(Shop.New(name, address, city, timetable, phoneNumber));
        }

        #endregion
    }

    sealed partial class IngredientShopRating : IRating<IIngredient, ShopRating>, IOtherRating<IShop, ShopRating>
    {
        #region IOtherRating<IShop,ShopRating> Members

        IShop IOtherRating<IShop, ShopRating>.Entity
        {
            get { return Shop; }
        }

        int IOtherRating<IShop, ShopRating>.Id
        {
            get { return ShopId; }
        }

        string IOtherRating<IShop, ShopRating>.Name
        {
            get { return Shop.Name; }
        }

        ShopRating IOtherRating<IShop, ShopRating>.Rating
        {
            get { return (ShopRating) Rating; }
        }

        #endregion

        #region IRating<IIngredient,ShopRating> Members

        IIngredient IRating<IIngredient, ShopRating>.Entity
        {
            get { return Ingredient; }
        }

        int IEntity.Id
        {
            get { return IngredientId; }
        }

        string INamedEntity.Name
        {
            get { return Ingredient.Name; }
        }

        ShopRating IRating<IIngredient, ShopRating>.Rating
        {
            get { return (ShopRating) Rating; }
        }

        public void Update(ShopRating rating)
        {
            Rating = (byte) rating;
            Manager.SaveChanges();
        }

        #endregion
    }

    sealed class ShopRatings : NamedLinkSet<IngredientShopRating, IRating<IIngredient, ShopRating>>,
                               IRatings<IIngredient, ShopRating>
    {
        public ShopRatings(Func<EntityCollection<IngredientShopRating>> items, Func<int> idGetter)
            : base(items, idGetter)
        {
        }

        #region IRatings<IIngredient,ShopRating> Members

        public INamedEntities<IIngredient> Entities
        {
            get { return Manager.Ingredients; }
        }

        public IRating<IIngredient, ShopRating> Add(string name, ShopRating rating)
        {
            return Add(IngredientShopRating.CreateIngredientShopRating(IdGetter(), Entities[name].Id, (byte) rating));
        }

        #endregion
    }
}